package imp

import (
	sqlc "bgs/db/sqlc"
	commonGrpc "bgs/grpc/gen/service/common"
	"bgs/grpc/gen/shared/message"
	"bgs/grpc/imp/enums"
	activityService "bgs/service/activity"
	"bgs/service/model"
	"bgs/util"
	"context"
	"fmt"
)

/****************************************************************************************/
/*                            expressPlatform entity of helper                        */
/****************************************************************************************/

func transformExpressPlatformInfoEntityToPb(o *model.ExpressPlatform) *message.ExpressPlatformInfo {
	return &message.ExpressPlatformInfo{
		Id:   o.ID,
		Name: o.Name,
	}
}

func mapExpressPlatformInfoEntityToPb(list []*model.ExpressPlatform, f func(*model.ExpressPlatform) *message.ExpressPlatformInfo) []*message.ExpressPlatformInfo {
	r := make([]*message.ExpressPlatformInfo, len(list))
	for i, item := range list {
		r[i] = f(item)
	}
	return r
}

/****************************************************************************************/
/*                            expressPlatform of query                                  */
/****************************************************************************************/

// ListExpressPlatforms  获取物流平台列表
func (s *CommonAPIService) ListExpressPlatforms(ctx context.Context, req *commonGrpc.ListExpressPlatformsRequest) (res *commonGrpc.ListExpressPlatformsResponse, err error) {
	slog := s.NewContextLogger(ctx)
	slog.Infof("commonImp->ListExpressPlatforms:%v", req)
	res = &commonGrpc.ListExpressPlatformsResponse{
		OpRet: &message.OperationResult{
			Success: true,
			Code:    0,
		},
	}

	expressPlatforms, err := s.warehouseService.GetCommonExpressPlatforms(ctx)
	if err != nil {
		res.OpRet = &message.OperationResult{
			Success: false,
			Code:    400,
			Msg:     err.Error(),
		}
		return
	}
	res.ExpressPlatforms = mapExpressPlatformInfoEntityToPb(expressPlatforms, transformExpressPlatformInfoEntityToPb)
	return
}

/****************************************************************************************/
/*                            SearchObject entity of helper                             */
/****************************************************************************************/

func transformSearchObjectEntityToPb(v interface{}) *message.SearchObject {
	switch o := v.(type) {
	case sqlc.ListSearchObjectsOfBrandOwnActivityRow:
		// o := v.(sqlc.ListSearchObjectsOfBrandOwnActivityRow)
		return &message.SearchObject{
			Id:   o.ID,
			Name: o.Name,
		}
	case sqlc.ListSearchObjectsOfBrandDistributorRow:
		// o := v.(sqlc.ListSearchObjectsOfBrandDistributorRow)
		return &message.SearchObject{
			Id:   o.ID,
			Name: o.Name,
		}
	case sqlc.ListSearchObjectsOfBrandSpokesmanRow:
		// o := v.(sqlc.ListSearchObjectsOfBrandSpokesmanRow)
		return &message.SearchObject{
			Id:   o.ID,
			Name: o.Name,
		}
	case sqlc.ListSearchObjectsOfStoreOwnActivityRow:
		// o := v.(sqlc.ListSearchObjectsOfStoreOwnActivityRow)
		return &message.SearchObject{
			Id:   o.ID,
			Name: o.Name,
		}
	case sqlc.ListSearchObjectsOfStoreSpokesmanRow:
		// o := v.(sqlc.ListSearchObjectsOfStoreSpokesmanRow)
		return &message.SearchObject{
			Id:   o.ID,
			Name: o.Name,
		}
	case sqlc.ListSearchObjectsOfSpokesmanOwnActivityRow:
		// o := v.(sqlc.ListSearchObjectsOfSpokesmanOwnActivityRow)
		return &message.SearchObject{
			Id:   o.ID,
			Name: o.Name,
		}
	case sqlc.ListSearchObjectsOfBrandForUserEndorsedRow:
		// o := v.(sqlc.ListSearchObjectsOfBrandForUserEndorsedRow)
		return &message.SearchObject{
			Id:   o.ID,
			Name: o.Name,
		}
	case sqlc.ListSearchObjectsOfStoreForUserEndorsedRow:
		// o := v.(sqlc.ListSearchObjectsOfStoreForUserEndorsedRow)
		return &message.SearchObject{
			Id:   o.ID,
			Name: o.Name,
		}
	default:
		return nil
	}
}

func mapSearchObjectEntityToPb(list []interface{}, f func(interface{}) *message.SearchObject) []*message.SearchObject {
	r := make([]*message.SearchObject, len(list))
	for i, item := range list {
		r[i] = f(item)
	}
	return r
}

/****************************************************************************************/
/*                            SearchObject of query                                     */
/****************************************************************************************/

// ListSearchObjectsAsBrand  列出查询对象(B视角)
func (s *CommonAPIService) ListSearchObjectsAsBrand(ctx context.Context, req *commonGrpc.ListSearchObjectsAsBrandRequest) (res *commonGrpc.ListSearchObjectsResponse, err error) {
	slog := s.NewContextLogger(ctx)
	slog.Infof("commonImp->ListSearchObjectsAsBrand:%v", req)
	res = &commonGrpc.ListSearchObjectsResponse{
		OpRet: &message.OperationResult{
			Success: true,
			Code:    0,
		},
	}

	q := s.dao.Q
	limit := req.Limit
	offset := req.Offset
	brandID := req.BrandId
	searchTerm := req.SearchTerm
	isKeywordEmpty := req.Keyword == ""
	keywordLike := fmt.Sprintf("%%%s%%", req.Keyword)

	var total int64
	var sqlErr error
	var searchObjects []interface{}

	switch searchTerm {
	default:
		res.OpRet = &message.OperationResult{
			Success: false,
			Code:    400,
			Msg:     fmt.Sprintf("无效的searchTerm:%s", searchTerm),
		}
		return res, nil
	case string(enums.SearchTermActivity):
		types := activityService.ActivitiesAsFeature

		total, sqlErr = q.CountSearchObjectsOfBrandOwnActivity(ctx, sqlc.CountSearchObjectsOfBrandOwnActivityParams{
			AsFeatureTypes: types,
			BrandID:        brandID,
			IsKeywordEmpty: isKeywordEmpty,
			Keyword:        keywordLike,
		})
		if err != nil {
			err = sqlErr
		} else {
			if total == 0 {
				// 不用继续调用listfunc
				return
			}
		}
		rows, sqlErr := q.ListSearchObjectsOfBrandOwnActivity(ctx, sqlc.ListSearchObjectsOfBrandOwnActivityParams{
			Limit:          limit,
			Offset:         offset,
			AsFeatureTypes: types,
			BrandID:        brandID,
			IsKeywordEmpty: isKeywordEmpty,
			Keyword:        keywordLike,
		})
		if sqlErr != nil {
			err = sqlErr
		} else {
			searchObjects = util.ToGenericSlice(rows)
		}
	case string(enums.SearchTermDistributor):
		total, sqlErr = q.CountSearchObjectsOfBrandDistributor(ctx, sqlc.CountSearchObjectsOfBrandDistributorParams{
			BrandID:        brandID,
			IsKeywordEmpty: isKeywordEmpty,
			Keyword:        keywordLike,
		})
		if err != nil {
			err = sqlErr
		} else {
			if total == 0 {
				// 不用继续调用listfunc
				return
			}
		}
		rows, sqlErr := q.ListSearchObjectsOfBrandDistributor(ctx, sqlc.ListSearchObjectsOfBrandDistributorParams{
			Limit:          limit,
			Offset:         offset,
			BrandID:        brandID,
			IsKeywordEmpty: isKeywordEmpty,
			Keyword:        keywordLike,
		})
		if sqlErr != nil {
			err = sqlErr
		} else {
			searchObjects = util.ToGenericSlice(rows)
		}
	case string(enums.SearchTermSpokesman):
		total, sqlErr = q.CountSearchObjectsOfBrandSpokesman(ctx, sqlc.CountSearchObjectsOfBrandSpokesmanParams{
			BrandID:        brandID,
			IsKeywordEmpty: isKeywordEmpty,
			Keyword:        keywordLike,
		})
		if err != nil {
			err = sqlErr
		} else {
			if total == 0 {
				// 不用继续调用listfunc
				return
			}
		}
		rows, sqlErr := q.ListSearchObjectsOfBrandSpokesman(ctx, sqlc.ListSearchObjectsOfBrandSpokesmanParams{
			Limit:          limit,
			Offset:         offset,
			BrandID:        brandID,
			IsKeywordEmpty: isKeywordEmpty,
			Keyword:        keywordLike,
		})
		if sqlErr != nil {
			err = sqlErr
		} else {
			searchObjects = util.ToGenericSlice(rows)
		}
	}

	if err != nil {
		res.OpRet = &message.OperationResult{
			Success: false,
			Code:    400,
			Msg:     err.Error(),
		}
		return
	}

	res.SearchObjects = mapSearchObjectEntityToPb(searchObjects, transformSearchObjectEntityToPb)
	return
}

// ListSearchObjectsAsStore  列出查询对象(Store视角)
func (s *CommonAPIService) ListSearchObjectsAsStore(ctx context.Context, req *commonGrpc.ListSearchObjectsAsStoreRequest) (res *commonGrpc.ListSearchObjectsResponse, err error) {
	slog := s.NewContextLogger(ctx)
	slog.Infof("commonImp->ListSearchObjectsAsStore:%v", req)
	res = &commonGrpc.ListSearchObjectsResponse{
		OpRet: &message.OperationResult{
			Success: true,
			Code:    0,
		},
	}

	q := s.dao.Q
	limit := req.Limit
	offset := req.Offset
	storeID := req.StoreId
	searchTerm := req.SearchTerm
	isKeywordEmpty := req.Keyword == ""
	keywordLike := fmt.Sprintf("%%%s%%", req.Keyword)

	var total int64
	var sqlErr error
	var searchObjects []interface{}

	switch searchTerm {
	default:
		res.OpRet = &message.OperationResult{
			Success: false,
			Code:    400,
			Msg:     fmt.Sprintf("无效的searchTerm:%s", searchTerm),
		}
		return res, nil
	case string(enums.SearchTermActivity):
		types := activityService.ActivitiesAsFeature

		total, sqlErr = q.CountSearchObjectsOfStoreOwnActivity(ctx, sqlc.CountSearchObjectsOfStoreOwnActivityParams{
			AsFeatureTypes: types,
			StoreID:        sqlc.NInt64FromInt64(storeID),
			IsKeywordEmpty: isKeywordEmpty,
			Keyword:        keywordLike,
		})
		if err != nil {
			err = sqlErr
		} else {
			if total == 0 {
				// 不用继续调用listfunc
				return
			}
		}
		rows, sqlErr := q.ListSearchObjectsOfStoreOwnActivity(ctx, sqlc.ListSearchObjectsOfStoreOwnActivityParams{
			Limit:          limit,
			Offset:         offset,
			AsFeatureTypes: types,
			StoreID:        sqlc.NInt64FromInt64(storeID),
			IsKeywordEmpty: isKeywordEmpty,
			Keyword:        keywordLike,
		})
		if sqlErr != nil {
			err = sqlErr
		} else {
			searchObjects = util.ToGenericSlice(rows)
		}
	case string(enums.SearchTermSpokesman):
		total, sqlErr = q.CountSearchObjectsOfStoreSpokesman(ctx, sqlc.CountSearchObjectsOfStoreSpokesmanParams{
			StoreID:        sqlc.NInt64FromInt64(storeID),
			IsKeywordEmpty: isKeywordEmpty,
			Keyword:        keywordLike,
		})
		if err != nil {
			err = sqlErr
		} else {
			if total == 0 {
				// 不用继续调用listfunc
				return
			}
		}
		rows, sqlErr := q.ListSearchObjectsOfStoreSpokesman(ctx, sqlc.ListSearchObjectsOfStoreSpokesmanParams{
			Limit:          limit,
			Offset:         offset,
			StoreID:        sqlc.NInt64FromInt64(storeID),
			IsKeywordEmpty: isKeywordEmpty,
			Keyword:        keywordLike,
		})
		if sqlErr != nil {
			err = sqlErr
		} else {
			searchObjects = util.ToGenericSlice(rows)
		}
	}

	if err != nil {
		res.OpRet = &message.OperationResult{
			Success: false,
			Code:    400,
			Msg:     err.Error(),
		}
		return
	}

	res.SearchObjects = mapSearchObjectEntityToPb(searchObjects, transformSearchObjectEntityToPb)
	return
}

// ListSearchObjectsAsSpokesman  列出查询对象(S视角)
func (s *CommonAPIService) ListSearchObjectsAsSpokesman(ctx context.Context, req *commonGrpc.ListSearchObjectsAsSpokesmanRequest) (res *commonGrpc.ListSearchObjectsResponse, err error) {
	slog := s.NewContextLogger(ctx)
	slog.Infof("commonImp->ListSearchObjectsAsSpokesman:%v", req)
	res = &commonGrpc.ListSearchObjectsResponse{
		OpRet: &message.OperationResult{
			Success: true,
			Code:    0,
		},
	}

	q := s.dao.Q
	limit := req.Limit
	offset := req.Offset
	spokesmanUserID := req.SpokesmanUserId
	searchTerm := req.SearchTerm
	isKeywordEmpty := req.Keyword == ""
	keywordLike := fmt.Sprintf("%%%s%%", req.Keyword)

	var total int64
	var sqlErr error
	var searchObjects []interface{}

	switch searchTerm {
	default:
		res.OpRet = &message.OperationResult{
			Success: false,
			Code:    400,
			Msg:     fmt.Sprintf("无效的searchTerm:%s", searchTerm),
		}
		return res, nil
	case string(enums.SearchTermActivity):
		total, sqlErr = q.CountSearchObjectsOfSpokesmanOwnActivity(ctx, sqlc.CountSearchObjectsOfSpokesmanOwnActivityParams{
			PubUserID:      spokesmanUserID,
			IsKeywordEmpty: isKeywordEmpty,
			Keyword:        keywordLike,
		})
		if err != nil {
			err = sqlErr
		} else {
			if total == 0 {
				// 不用继续调用listfunc
				return
			}
		}
		rows, sqlErr := q.ListSearchObjectsOfSpokesmanOwnActivity(ctx, sqlc.ListSearchObjectsOfSpokesmanOwnActivityParams{
			Limit:          limit,
			Offset:         offset,
			PubUserID:      spokesmanUserID,
			IsKeywordEmpty: isKeywordEmpty,
			Keyword:        keywordLike,
		})
		if sqlErr != nil {
			err = sqlErr
		} else {
			searchObjects = util.ToGenericSlice(rows)
		}
	case string(enums.SearchTermBrand):
		total, sqlErr = q.CountSearchObjectsOfBrandForUserEndorsed(ctx, sqlc.CountSearchObjectsOfBrandForUserEndorsedParams{
			UserID:         spokesmanUserID,
			IsKeywordEmpty: isKeywordEmpty,
			Keyword:        keywordLike,
		})
		if err != nil {
			err = sqlErr
		} else {
			if total == 0 {
				// 不用继续调用listfunc
				return
			}
		}
		rows, sqlErr := q.ListSearchObjectsOfBrandForUserEndorsed(ctx, sqlc.ListSearchObjectsOfBrandForUserEndorsedParams{
			Limit:          limit,
			Offset:         offset,
			UserID:         spokesmanUserID,
			IsKeywordEmpty: isKeywordEmpty,
			Keyword:        keywordLike,
		})
		if sqlErr != nil {
			err = sqlErr
		} else {
			searchObjects = util.ToGenericSlice(rows)
		}
	case string(enums.SearchTermStore):
		total, sqlErr = q.CountSearchObjectsOfStoreForUserEndorsed(ctx, sqlc.CountSearchObjectsOfStoreForUserEndorsedParams{
			UserID:         spokesmanUserID,
			IsKeywordEmpty: isKeywordEmpty,
			Keyword:        keywordLike,
		})
		if err != nil {
			err = sqlErr
		} else {
			if total == 0 {
				// 不用继续调用listfunc
				return
			}
		}
		rows, sqlErr := q.ListSearchObjectsOfStoreForUserEndorsed(ctx, sqlc.ListSearchObjectsOfStoreForUserEndorsedParams{
			Limit:          limit,
			Offset:         offset,
			UserID:         spokesmanUserID,
			IsKeywordEmpty: isKeywordEmpty,
			Keyword:        keywordLike,
		})
		if sqlErr != nil {
			err = sqlErr
		} else {
			searchObjects = util.ToGenericSlice(rows)
		}
	}

	if err != nil {
		res.OpRet = &message.OperationResult{
			Success: false,
			Code:    400,
			Msg:     err.Error(),
		}
		return
	}

	res.SearchObjects = mapSearchObjectEntityToPb(searchObjects, transformSearchObjectEntityToPb)
	return
}
